diff: Introduce GskDiffSettings
authorBenjamin Otte <otte@redhat.com>
Sat, 31 Mar 2018 09:02:32 +0000 (11:02 +0200)
committerBenjamin Otte <otte@redhat.com>
Thu, 5 Apr 2018 12:56:38 +0000 (14:56 +0200)
We can put lots of settings there to allow tuning the diff algorithm
used.

gsk/gskdiff.c
gsk/gskdiffprivate.h
gsk/gskrendernodeimpl.c

index 8d6e992a3aed49af03045c95c2f97b507e264155..195349609373e2ce5606ab303f19091b44514671 100644 (file)
 #define XDL_K_HEUR 4
 #define MAXCOST 20
 
+struct _GskDiffSettings {
+  GCompareDataFunc        compare_func;
+  GskKeepFunc             keep_func;
+  GskDeleteFunc           delete_func;
+  GskInsertFunc           insert_func;
+};
+
 typedef struct _SplitResult {
   long i1, i2;
   int min_lo, min_hi;
 } SplitResult;
 
+GskDiffSettings *
+gsk_diff_settings_new (GCompareDataFunc compare_func,
+                       GskKeepFunc      keep_func,
+                       GskDeleteFunc    delete_func,
+                       GskInsertFunc    insert_func)
+{
+  GskDiffSettings *settings;
+
+  settings = g_slice_new0 (GskDiffSettings);
+
+  settings->compare_func = compare_func;
+  settings->keep_func = keep_func;
+  settings->delete_func = delete_func;
+  settings->insert_func = insert_func;
+
+  return settings;
+}
+
+void
+gsk_diff_settings_free (GskDiffSettings *settings)
+{
+  g_slice_free (GskDiffSettings, settings);
+}
+
 /*
  * See "An O(ND) Difference Algorithm and its Variations", by Eugene Myers.
  * Basically considers a "box" (off1, off2, lim1, lim2) and scan from both
@@ -46,18 +77,18 @@ typedef struct _SplitResult {
  * to cut the search and to return a suboptimal point.
  */
 static void
-split (gconstpointer    *elem1,
-       gssize            off1,
-       gssize            lim1,
-       gconstpointer    *elem2,
-       gssize            off2,
-       gssize            lim2,
-       gssize           *kvdf,
-       gssize           *kvdb,
-       gboolean          need_min,
-       GCompareDataFunc  compare_func,
-       gpointer          data,
-       SplitResult      *spl)
+split (gconstpointer         *elem1,
+       gssize                 off1,
+       gssize                 lim1,
+       gconstpointer         *elem2,
+       gssize                 off2,
+       gssize                 lim2,
+       gssize                *kvdf,
+       gssize                *kvdb,
+       gboolean               need_min,
+       const GskDiffSettings *settings,
+       gpointer               data,
+       SplitResult           *spl)
 {
   gssize dmin = off1 - lim2, dmax = lim1 - off2;
   gssize fmid = off1 - off2, bmid = lim1 - lim2;
@@ -102,7 +133,7 @@ split (gconstpointer    *elem1,
           i2 = i1 - d;
           for (; i1 < lim1 && i2 < lim2; i1++, i2++)
             {
-              if (compare_func (elem1[i1], elem2[i2], data) != 0)
+              if (settings->compare_func (elem1[i1], elem2[i2], data) != 0)
                 break;
             }
           if (i1 - prev1 > XDL_SNAKE_CNT)
@@ -143,7 +174,7 @@ split (gconstpointer    *elem1,
           i2 = i1 - d;
           for (; i1 > off1 && i2 > off2; i1--, i2--)
             {
-              if (compare_func (elem1[i1 - 1], elem2[i2 - 1], data) != 0)
+              if (settings->compare_func (elem1[i1 - 1], elem2[i2 - 1], data) != 0)
                 break;
             }
           if (prev1 - i1 > XDL_SNAKE_CNT)
@@ -186,7 +217,7 @@ split (gconstpointer    *elem1,
                 {
                   for (k = 1; ; k++)
                     {
-                      if (compare_func (elem1[i1 - k], elem2[i2 - k], data) != 0)
+                      if (settings->compare_func (elem1[i1 - k], elem2[i2 - k], data) != 0)
                         break;
                       if (k == XDL_SNAKE_CNT)
                         {
@@ -218,7 +249,7 @@ split (gconstpointer    *elem1,
                 {
                   for (k = 0; ; k++)
                     {
-                      if (compare_func (elem1[i1 + k], elem2[i2 + k], data) != 0)
+                      if (settings->compare_func (elem1[i1 + k], elem2[i2 + k], data) != 0)
                         break;
 
                       if (k == XDL_SNAKE_CNT - 1)
@@ -310,10 +341,7 @@ compare (gconstpointer             *elem1,
          gssize                    *kvdf,
          gssize                    *kvdb,
          gboolean                   need_min,
-         GCompareDataFunc           compare_func,
-         GskKeepFunc                keep_func,
-         GskDeleteFunc              delete_func,
-         GskInsertFunc              insert_func,
+         const GskDiffSettings     *settings,
          gpointer                   data)
 {
   /*
@@ -321,18 +349,18 @@ compare (gconstpointer             *elem1,
    */
   for (; off1 < lim1 && off2 < lim2; off1++, off2++)
     {
-      if (compare_func (elem1[off1], elem2[off2], data) != 0)
+      if (settings->compare_func (elem1[off1], elem2[off2], data) != 0)
         break;
 
-      keep_func (elem1[off1], elem2[off2], data);
+      settings->keep_func (elem1[off1], elem2[off2], data);
     }
 
   for (; off1 < lim1 && off2 < lim2; lim1--, lim2--)
     {
-      if (compare_func (elem1[lim1 - 1], elem2[lim2 - 1], data) != 0)
+      if (settings->compare_func (elem1[lim1 - 1], elem2[lim2 - 1], data) != 0)
         break;
 
-      keep_func (elem1[lim1 - 1], elem2[lim2 - 1], data);
+     settings-> keep_func (elem1[lim1 - 1], elem2[lim2 - 1], data);
     }
 
   /*
@@ -343,14 +371,14 @@ compare (gconstpointer             *elem1,
     {
       for (; off2 < lim2; off2++)
         {
-          insert_func (elem2[off2], off2, data);
+          settings->insert_func (elem2[off2], off2, data);
         }
     }
   else if (off2 == lim2)
     {
       for (; off1 < lim1; off1++)
         {
-          delete_func (elem1[off1], off1, data);
+          settings->delete_func (elem1[off1], off1, data);
         }
     }
   else
@@ -363,7 +391,7 @@ compare (gconstpointer             *elem1,
       split (elem1, off1, lim1,
              elem2, off2, lim2,
              kvdf, kvdb, need_min,
-             compare_func, data,
+             settings, data,
              &spl);
       /*
        * ... et Impera.
@@ -371,11 +399,11 @@ compare (gconstpointer             *elem1,
       compare (elem1, off1, spl.i1,
                elem2, off2, spl.i2,
                kvdf, kvdb, spl.min_lo,
-               compare_func, keep_func, delete_func, insert_func, data);
+               settings, data);
       compare (elem1, spl.i1, lim1,
                elem2, spl.i2, lim2,
                kvdf, kvdb, spl.min_hi,
-               compare_func, keep_func, delete_func, insert_func, data);
+               settings, data);
     }
 }
 
@@ -412,10 +440,7 @@ gsk_diff (gconstpointer             *elem1,
           gsize                      n1,
           gconstpointer             *elem2,
           gsize                      n2,
-          GCompareDataFunc           compare_func,
-          GskKeepFunc                keep_func,
-          GskDeleteFunc              delete_func,
-          GskInsertFunc              insert_func,
+          const GskDiffSettings     *settings,
           gpointer                   data)
 {
   gsize ndiags;
@@ -432,7 +457,7 @@ gsk_diff (gconstpointer             *elem1,
   compare (elem1, 0, n1,
            elem2, 0, n2,
            kvdf, kvdb, FALSE,
-           compare_func, keep_func, delete_func, insert_func, data);
+           settings, data);
 
   g_free (kvd);
 }
index 1c41e5d02e749ae21552e253e09264f50ffccf8d..240c1c17bd7600546e4903e1e9c6535e6c58549f 100644 (file)
@@ -28,15 +28,20 @@ typedef void (* GskKeepFunc)   (gconstpointer elem1, gconstpointer elem2, gpoint
 typedef void (* GskDeleteFunc) (gconstpointer elem, gsize idx, gpointer data);
 typedef void (* GskInsertFunc) (gconstpointer elem, gsize idx, gpointer data);
 
-void            gsk_diff                         (gconstpointer             *elem1,
-                                                  gsize                      n1,
-                                                  gconstpointer             *elem2,
-                                                  gsize                      n2,
-                                                  GCompareDataFunc           compare_func,
-                                                  GskKeepFunc                keep_func,
-                                                  GskDeleteFunc              delete_func,
-                                                  GskInsertFunc              insert_func,
-                                                  gpointer                   data);
+typedef struct _GskDiffSettings GskDiffSettings;
+
+GskDiffSettings *       gsk_diff_settings_new                   (GCompareDataFunc        compare_func,
+                                                                 GskKeepFunc             keep_func,
+                                                                 GskDeleteFunc           delete_func,
+                                                                 GskInsertFunc           insert_func);
+void                    gsk_diff_settings_free                  (GskDiffSettings        *settings);
+
+void                    gsk_diff                                (gconstpointer          *elem1,
+                                                                 gsize                   n1,
+                                                                 gconstpointer          *elem2,
+                                                                 gsize                   n2,
+                                                                 const GskDiffSettings  *settings,
+                                                                 gpointer                data);
 
 G_END_DECLS
 
index 3c32743813eae7bc6c7f8b1cc2e6a43e93e48ce7..d1dbfae12f8c81dee374947ad5aa43daadc59cc5 100644 (file)
@@ -2181,6 +2181,22 @@ gsk_container_node_change_func (gconstpointer elem, gsize idx, gpointer data)
   gsk_render_node_add_to_region ((GskRenderNode *) elem, data);
 }
 
+static GskDiffSettings *
+gsk_container_node_get_diff_settings (void)
+{
+  static GskDiffSettings *settings = NULL;
+
+  if (G_LIKELY (settings))
+    return settings;
+
+  settings = gsk_diff_settings_new (gsk_container_node_compare_func,
+                                    gsk_container_node_keep_func,
+                                    gsk_container_node_change_func,
+                                    gsk_container_node_change_func);
+
+  return settings;
+}
+
 static void
 gsk_container_node_diff (GskRenderNode  *node1,
                          GskRenderNode  *node2,
@@ -2193,10 +2209,7 @@ gsk_container_node_diff (GskRenderNode  *node1,
             self1->n_children,
             (gconstpointer *) self2->children,
             self2->n_children,
-            gsk_container_node_compare_func,
-            gsk_container_node_keep_func,
-            gsk_container_node_change_func,
-            gsk_container_node_change_func,
+            gsk_container_node_get_diff_settings (),
             region);
 }